package com.huanghuai.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.huanghuai.entity.SysUser;
import com.huanghuai.util.JwtUtils;
import com.huanghuai.vo.HttpResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.coyote.Response;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ValidateCodeFilter extends OncePerRequestFilter {

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private JwtUtils jwtUtils;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        if(requestURI.equals("/login/doLogin") || requestURI.equals("/code/image")){
            doFilter(request,response,filterChain);//不是登录请求直接放行
            return;
        }
        //校验验证码
        validateCode(request,response,filterChain);
        String strAuth = request.getHeader("Authorization");
        if(StringUtils.isEmpty(strAuth)){
            HttpResult httpResult = HttpResult.builder()
                    .code(0)
                    .msg("jwt 为空")
                    .build();
            printToken(request,response,httpResult );
            return;
        }
        String jwtToken = strAuth.replace("bearer", "");
        if(StringUtils.containsWhitespace(jwtToken)){
            HttpResult httpResult = HttpResult.builder()
                    .code(0)
                    .msg("jwt 为空")
                    .build();
            printToken(request,response,httpResult );
            return;
        }
        boolean verifyResult = jwtUtils.verifyToken(jwtToken);
        if(!verifyResult){
            HttpResult httpResult = HttpResult.builder()
                    .code(0)
                    .msg("jwt 不合法")
                    .build();
            printToken(request,response,httpResult );
            return;
        }
        //从jwt里获取用户信息和权限信息
        String userInfo = jwtUtils.getUserInfoFromToken(jwtToken);
        List<String> authFromToken = jwtUtils.getUserAuthFromToken(jwtToken);
        //反序列化为SysUser对象
        SysUser sysUser = objectMapper.readValue(userInfo, SysUser.class);
        List<SimpleGrantedAuthority> authorities = authFromToken.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
        //用户名密码认证token
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(sysUser,null,authorities);
        //把token放到安全上下文：securityContext;
        SecurityContextHolder.getContext().setAuthentication(token);
        doFilter(request,response,filterChain);//放行

    }


    private void printToken(HttpServletRequest request, HttpServletResponse response, HttpResult httpResult) throws IOException {
        String strResponse = objectMapper.writeValueAsString(httpResult);
        response.setCharacterEncoding("UTF-8");//设置响应字符集
        response.setContentType("application/json;charset=utf-8");//设置响应内容类型
        PrintWriter writer = response.getWriter();//获取书写区
        writer.println(strResponse);
        writer.flush();
    }

    private void validateCode(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        //从前端获取验证码
        String code = request.getParameter("code");
        //从Session中获取验证码
        String captcha = (String)request.getSession().getAttribute("CAPTCHA");
        request.getSession().removeAttribute("captcha_code_error");//清除错误信息
        //判断二者是否相等
        if(StringUtils.isEmpty(code)){
            request.getSession().setAttribute("captcha_code_error","请输入验证码");
            response.sendRedirect("/toLogin");
            return;
        }
        if(StringUtils.isEmpty(captcha)){
            request.getSession().setAttribute("captcha_code_error","验证码错误");
            response.sendRedirect("/toLogin");
            return;
        }
        if(!code.equalsIgnoreCase(captcha)){
            request.getSession().setAttribute("captcha_code_error","验证码输入错误");
            response.sendRedirect("/toLogin");
            return;
        }
        request.getSession().removeAttribute("captcha_code_error");//删除session中的验证码
        this.doFilter(request,response,filterChain);
    }
}
